package com.djj.nanny.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import com.djj.nanny.entity.ChatMessage;
import com.djj.nanny.entity.ChatSession;
import com.djj.nanny.entity.ServiceStaff;
import com.djj.nanny.entity.User;
import com.djj.nanny.exception.ServiceException;
import com.djj.nanny.mapper.ChatMessageMapper;
import com.djj.nanny.mapper.ChatSessionMapper;
import com.djj.nanny.mapper.ServiceStaffMapper;
import com.djj.nanny.mapper.UserMapper;
import com.djj.nanny.service.ChatService;
import com.djj.nanny.websocket.ChatWebSocketServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class ChatServiceImpl implements ChatService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ChatServiceImpl.class);

    @Resource
    private ChatMessageMapper messageMapper;

    @Resource
    private ChatSessionMapper sessionMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private ServiceStaffMapper staffMapper;
    
    @Resource
    private ObjectMapper objectMapper;


    
    /**
     * 获取聊天会话列表
     */
    public Page<ChatSession> getChatSessions(Long userId, Integer pageNum, Integer pageSize) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }
        
        LambdaQueryWrapper<ChatSession> queryWrapper = new LambdaQueryWrapper<>();
        
        if ("STAFF".equals(user.getRoleCode())) {
            // 如果是服务人员，查找服务人员ID
            ServiceStaff staff = staffMapper.selectOne(
                new LambdaQueryWrapper<ServiceStaff>()
                    .eq(ServiceStaff::getUserId, userId)
            );
            
            if (staff != null) {
                queryWrapper.eq(ChatSession::getStaffId, staff.getId());
            } else {
                // 如果找不到服务人员记录，直接返回空结果
                return new Page<>(pageNum, pageSize);
            }
        } else {
            // 普通用户直接查询
            queryWrapper.eq(ChatSession::getUserId, userId);
        }
        
        queryWrapper.orderByDesc(ChatSession::getUpdateTime);
        Page<ChatSession> page = sessionMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
        
        // 填充用户和服务人员信息
        for (ChatSession session : page.getRecords()) {
            session.setUser(userMapper.selectById(session.getUserId()));
            ServiceStaff staff = staffMapper.selectById(session.getStaffId());
            if (staff != null) {
                staff.setUser(userMapper.selectById(staff.getUserId()));
                session.setStaff(staff);
            }
        }
        
        return page;
    }

    /**
     * 标记消息为已读
     */
    @Transactional(rollbackFor = Exception.class)
    public void markMessagesAsRead(Long sessionId, Long userId) {
        // 更新消息状态
        ChatMessage updateMessage = new ChatMessage();
        updateMessage.setReadStatus(1);
        
        messageMapper.update(updateMessage, new LambdaQueryWrapper<ChatMessage>()
            .eq(ChatMessage::getSessionId, sessionId)
            .eq(ChatMessage::getReceiverId, userId)
            .eq(ChatMessage::getReadStatus, 0));

        // 重置会话未读数
        ChatSession session = sessionMapper.selectById(sessionId);
        if (session != null) {
            // 只有当查看者是消息的接收者时才重置未读数
            if ((userId.equals(session.getUserId()) && !userId.equals(session.getLastSenderId())) || 
                (isStaffUser(userId, session.getStaffId()) && !isStaffUser(session.getLastSenderId(), session.getStaffId()))) {
                session.setUnreadCount(0);
            }
            sessionMapper.updateById(session);
            
            // 发送消息已读通知给发送者
            try {
                Map<String, Object> readNotification = new HashMap<>();
                readNotification.put("type", "message_read");
                readNotification.put("sessionId", sessionId);
                
                String notificationJson = objectMapper.writeValueAsString(readNotification);
                LOGGER.info("发送消息已读通知: {}", notificationJson);
                
                // 发送给最后一条消息的发送者
                if (session.getLastSenderId() != null) {
                    ChatWebSocketServer.sendMessage(session.getLastSenderId(), notificationJson);
                }
            } catch (Exception e) {
                LOGGER.error("发送消息已读通知失败", e);
            }
        }
    }

    /**
     * 判断用户是否是服务人员
     */
    public boolean isStaffUser(Long userId, Long staffId) {
        ServiceStaff staff = staffMapper.selectById(staffId);
        LOGGER.info("staff，{}",staff);
        return staff != null && Objects.equals(userId, staff.getUserId());
    }

    /**
     * 创建聊天会话
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> createSession(Long userId, Long staffId) {
        // 先查 user
        User user = userMapper.selectById(userId);

        ServiceStaff staff = staffMapper.selectById(staffId);

        if (staff == null) {
            throw new ServiceException("服务人员信息不存在");
        }
        User staffUser = userMapper.selectById(staff.getUserId());

        if (staffUser == null || !"STAFF".equals(staffUser.getRoleCode())) {
            throw new ServiceException("服务人员用户不存在或不是STAFF");
        }

        // 查重
        LambdaQueryWrapper<ChatSession> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatSession::getUserId, userId)
            .eq(ChatSession::getStaffId, staffId);

        ChatSession existingSession = sessionMapper.selectOne(queryWrapper);
        if (existingSession != null) {
            // 填充用户和服务人员信息
            existingSession.setUser(user);
            staff.setUser(staffUser);
            existingSession.setStaff(staff);
            return convertSessionToMap(existingSession);
        }

        // 创建新会话
        ChatSession session = new ChatSession();
        session.setUserId(userId);
        session.setStaffId(staffId);
        session.setUnreadCount(0);
        session.setLastSenderId(null);

        if (sessionMapper.insert(session) <= 0) {
            throw new ServiceException("创建会话失败");
        }

        // 填充用户和服务人员信息
        session.setUser(user);
        staff.setUser(staffUser);
        session.setStaff(staff);

        return convertSessionToMap(session);
    }

    private Map<String, Object> convertSessionToMap(ChatSession session) {
        Map<String, Object> response = new HashMap<>();
        response.put("id", session.getId());
        response.put("userId", session.getUserId());
        response.put("staffId", session.getStaffId());
        response.put("unreadCount", session.getUnreadCount());
        response.put("lastSenderId", session.getLastSenderId());
        response.put("lastMessage", session.getLastMessage());
        response.put("createTime", session.getCreateTime());
        response.put("updateTime", session.getUpdateTime());
        response.put("lastMessageTime", session.getLastMessageTime());
        return response;
    }
    
    /**
     * 发送消息
     */
    @Transactional(rollbackFor = Exception.class)
    public ChatMessage sendMessage(Long senderId, Long receiverId, String content) throws Exception {
        // 获取或创建会话
        ChatSession session = getOrCreateSession(senderId, receiverId);

        // 创建消息记录并保存
        ChatMessage message = createAndSaveMessage(session, senderId, receiverId, content);

        // 更新会话信息
        session.setLastMessage(content);
        // 只有当接收者查看会话时才增加未读数
        // 如果发送者是用户，则增加服务人员的未读数；如果发送者是服务人员，则增加用户的未读数
        if (senderId.equals(session.getUserId())) {
            // 用户发送消息，增加服务人员的未读数
            session.setUnreadCount(session.getUnreadCount() + 1);
        } else if (senderId.equals(getStaffUserIdByStaffId(session.getStaffId()))) {
            // 服务人员发送消息，增加用户的未读数
            session.setUnreadCount(session.getUnreadCount() + 1);
        }

        session.setLastSenderId(senderId);
        sessionMapper.updateById(session);

        // 发送消息给接收者
        Map<String, Object> response = new HashMap<>();
        response.put("id", message.getId());
        response.put("sessionId", message.getSessionId());
        response.put("senderId", senderId);
        response.put("receiverId", receiverId);
        response.put("content", content);
        response.put("createTime", message.getCreateTime());
        response.put("readStatus", message.getReadStatus());
        response.put("messageType", message.getMessageType());

        // 发送消息给接收者（如果是服务人员，receiverId 需通过 staffId 查 userId）
        Long realReceiverId = receiverId;
        if (receiverId.equals(session.getStaffId())) {
            // 如果 receiverId 是 staffId，查 userId
            realReceiverId = getStaffUserIdByStaffId(session.getStaffId());
        }
        extracted(senderId, content, response, realReceiverId, session);

        return message;
    }

    private void extracted(Long senderId, String content, Map<String, Object> response, Long realReceiverId, ChatSession session) throws JsonProcessingException {
        String messageJson = objectMapper.writeValueAsString(response);
        LOGGER.info("发送消息给接收者: {}", messageJson);
        ChatWebSocketServer.sendMessage(realReceiverId, messageJson);

        // 发送会话更新消息给发送者和接收者
        Map<String, Object> sessionUpdate = new HashMap<>();
        sessionUpdate.put("type", "session_update");
        sessionUpdate.put("sessionId", session.getId());
        sessionUpdate.put("lastMessage", content);
        sessionUpdate.put("lastSenderId", senderId);
        sessionUpdate.put("unreadCount", session.getUnreadCount());
        sessionUpdate.put("updateTime", session.getUpdateTime());

        String sessionUpdateJson = objectMapper.writeValueAsString(sessionUpdate);
        LOGGER.info("发送会话更新消息: {}", sessionUpdateJson);

        // 发送给发送者
        ChatWebSocketServer.sendMessage(senderId, sessionUpdateJson);
        // 发送给接收者
        ChatWebSocketServer.sendMessage(realReceiverId, sessionUpdateJson);
    }

    // 新增：通过 staffId 查 userId
    private Long getStaffUserIdByStaffId(Long staffId) {
        ServiceStaff staff = staffMapper.selectById(staffId);
        if (staff == null) return null;
        return staff.getUserId();
    }

    /**
     * 获取或创建会话
     */
    @Transactional(rollbackFor = Exception.class)
    public ChatSession getOrCreateSession(Long senderId, Long receiverId) {
        // 确定用户ID和服务人员ID
        Long userId;
        Long staffId;
        
        // 查询发送者和接收者的角色信息
        User sender = userMapper.selectById(senderId);
        User receiver = userMapper.selectById(receiverId);
        
        if (sender == null || receiver == null) {
            throw new ServiceException("用户不存在");
        }
        
        // 根据角色确定谁是用户谁是服务人员
        if ("STAFF".equals(sender.getRoleCode())) {
            // 查找发送者的服务人员ID
            ServiceStaff senderStaff = staffMapper.selectOne(
                new LambdaQueryWrapper<ServiceStaff>()
                    .eq(ServiceStaff::getUserId, senderId)
            );
            
            if (senderStaff != null) {
                staffId = senderStaff.getId();
                userId = receiverId;
            } else {
                throw new ServiceException("服务人员信息不存在");
            }
        } else if ("STAFF".equals(receiver.getRoleCode())) {
            // 查找接收者的服务人员ID
            ServiceStaff receiverStaff = staffMapper.selectOne(
                new LambdaQueryWrapper<ServiceStaff>()
                    .eq(ServiceStaff::getUserId, receiverId)
            );
            
            if (receiverStaff != null) {
                staffId = receiverStaff.getId();
                userId = senderId;
            } else {
                throw new ServiceException("服务人员信息不存在");
            }
        } else {
            throw new ServiceException("无法确定会话类型，至少需要一方是服务人员");
        }

        // 查询是否已存在会话
        LambdaQueryWrapper<ChatSession> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatSession::getUserId, userId)
            .eq(ChatSession::getStaffId, staffId);

        ChatSession session = sessionMapper.selectOne(queryWrapper);
        if (session != null) {
            return session;
        }

        // 创建新会话
        session = new ChatSession();
        session.setUserId(userId);
        session.setStaffId(staffId);
        session.setUnreadCount(0);
        session.setLastSenderId(null);
        
        if (sessionMapper.insert(session) <= 0) {
            throw new ServiceException("创建会话失败");
        }
        
        return session;
    }

    /**
     * 处理WebSocket消息
     */
    @Transactional(rollbackFor = Exception.class)
    public void handleMessage(String messageContent, Long senderId) throws Exception {
        LOGGER.info("收到WebSocket消息: senderId={}, content={}", senderId, messageContent);
        
        Map<String, Object> messageMap = objectMapper.readValue(messageContent, new TypeReference<>() {
        });
        Long receiverId = Long.valueOf(messageMap.get("receiverId").toString());
        String content = messageMap.get("content").toString();

        // 获取或创建会话
        ChatSession session = getOrCreateSession(senderId, receiverId);

        // 创建消息记录
        ChatMessage message = createAndSaveMessage(session, senderId, receiverId, content);

        LOGGER.info("消息已保存到数据库: messageId={}", message.getId());

        // 更新会话信息
        session.setLastMessage(content);

        // 只有当接收者查看会话时才增加未读数
        // 如果发送者是用户，则增加服务人员的未读数；如果发送者是服务人员，则增加用户的未读数
        if (senderId.equals(session.getUserId())) {
            // 用户发送消息，增加服务人员的未读数
            session.setUnreadCount(session.getUnreadCount() + 1);
        } else if (senderId.equals(session.getStaffId()) || isStaffUser(senderId, session.getStaffId())) {
            // 服务人员发送消息，增加用户的未读数
            session.setUnreadCount(session.getUnreadCount() + 1);
        }

        session.setLastSenderId(senderId);
        sessionMapper.updateById(session);
        LOGGER.info("会话信息已更新: sessionId={}", session.getId());

        // 发送消息给接收者
        Map<String, Object> response = new HashMap<>();
        response.put("id", message.getId());
        response.put("sessionId", message.getSessionId());
        response.put("senderId", senderId);
        response.put("receiverId", receiverId);
        response.put("content", content);
        response.put("createTime", message.getCreateTime());
        response.put("readStatus", message.getReadStatus());
        response.put("messageType", message.getMessageType());

        extracted(senderId, content, response, receiverId, session);

        LOGGER.info("消息处理完成: messageId={}", message.getId());
    }

    /**
     * 创建并保存消息
     */
    private ChatMessage createAndSaveMessage(ChatSession session, Long senderId, Long receiverId, String content) {
        ChatMessage message = new ChatMessage();
        message.setSessionId(session.getId());
        message.setSenderId(senderId);
        message.setReceiverId(receiverId);
        message.setContent(content);
        message.setReadStatus(0); // 初始状态为未读
        message.setMessageType(1);

        if (messageMapper.insert(message) <= 0) {
            throw new ServiceException("保存消息失败");
        }

        return message;
    }

    /**
     * 删除单条聊天消息
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteMessage(Long messageId) {
        LOGGER.info("开始删除消息: messageId={}", messageId);
        
        ChatMessage message = messageMapper.selectById(messageId);
        if (message == null) {
            throw new ServiceException("消息不存在");
        }
        
        // 获取会话信息
        ChatSession session = sessionMapper.selectById(message.getSessionId());
        if (session == null) {
            throw new ServiceException("会话不存在");
        }
        
        // 删除消息
        messageMapper.deleteById(messageId);
        LOGGER.info("消息已从数据库删除: messageId={}", messageId);
        
        // 检查是否是最后一条消息
        boolean isLastMessage = session.getLastMessage() != null && 
                              message.getContent().equals(session.getLastMessage()) &&
                              message.getSenderId().equals(session.getLastSenderId());
        
        if (isLastMessage) {
            LOGGER.info("删除的是最后一条消息，需要更新会话信息");
            // 查找新的最后一条消息
            ChatMessage lastMessage = messageMapper.selectOne(
                new LambdaQueryWrapper<ChatMessage>()
                    .eq(ChatMessage::getSessionId, session.getId())
                    .orderByDesc(ChatMessage::getCreateTime)
                    .last("LIMIT 1")
            );
            
            if (lastMessage != null) {
                session.setLastMessage(lastMessage.getContent());
                session.setLastSenderId(lastMessage.getSenderId());
                session.setUpdateTime(lastMessage.getCreateTime());
            } else {
                session.setLastMessage("");
                session.setLastSenderId(null);
                session.setUpdateTime(LocalDateTime.now());
            }
            
            // 更新会话信息
            if (sessionMapper.updateById(session) <= 0) {
                LOGGER.error("更新会话信息失败: sessionId={}", session.getId());
                throw new ServiceException("更新会话信息失败");
            }
            LOGGER.info("会话信息已更新: sessionId={}", session.getId());
        }
        
        // 发送消息删除通知给双方
        Map<String, Object> deleteNotification = new HashMap<>();
        deleteNotification.put("type", "message_deleted");
        deleteNotification.put("messageId", messageId);
        deleteNotification.put("sessionId", session.getId());
        
        try {
            String notificationJson = objectMapper.writeValueAsString(deleteNotification);
            LOGGER.info("发送删除通知: {}", notificationJson);
            
            // 发送给发送者
            ChatWebSocketServer.sendMessage(message.getSenderId(), notificationJson);
            // 发送给接收者
            ChatWebSocketServer.sendMessage(message.getReceiverId(), notificationJson);
            
            LOGGER.info("删除通知已发送给双方");
        } catch (Exception e) {
            LOGGER.error("发送消息删除通知失败", e);
        }
        
        LOGGER.info("删除消息流程完成: messageId={}", messageId);
    }

    /**
     * 清空会话的所有聊天记录
     */
    @Transactional(rollbackFor = Exception.class)
    public void clearSessionMessages(Long sessionId) {
        ChatSession session = sessionMapper.selectById(sessionId);
        if (session == null) {
            throw new ServiceException("会话不存在");
        }
        
        // 删除该会话下的所有消息
        LambdaQueryWrapper<ChatMessage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatMessage::getSessionId, sessionId);
        messageMapper.delete(queryWrapper);

        // 逻辑删除会话（通过注解实现）
        sessionMapper.deleteById(sessionId);

        // 更新会话信息
        session.setLastMessage("");
        session.setUnreadCount(0);
        sessionMapper.updateById(session);
        
        // 发送清空通知给双方
        Map<String, Object> clearNotification = new HashMap<>();
        clearNotification.put("type", "messages_cleared");
        clearNotification.put("sessionId", sessionId);
        
        try {
            String notificationJson = objectMapper.writeValueAsString(clearNotification);
            LOGGER.info("发送清空通知: {}", notificationJson);
            
            // 获取服务人员信息
            ServiceStaff staff = staffMapper.selectById(session.getStaffId());
            if (staff == null) {
                LOGGER.error("服务人员信息不存在: staffId={}", session.getStaffId());
                return;
            }
            
            // 发送给用户
            LOGGER.info("发送清空通知给用户: userId={}", session.getUserId());
            ChatWebSocketServer.sendMessage(session.getUserId(), notificationJson);
            
            // 发送给服务人员（使用服务人员的用户ID）
            LOGGER.info("发送清空通知给服务人员: staffUserId={}", staff.getUserId());
            ChatWebSocketServer.sendMessage(staff.getUserId(), notificationJson);
            
            // 发送会话更新消息
            Map<String, Object> sessionUpdate = new HashMap<>();
            sessionUpdate.put("type", "session_update");
            sessionUpdate.put("sessionId", sessionId);
            sessionUpdate.put("lastMessage", "");
            sessionUpdate.put("lastSenderId", null);
            sessionUpdate.put("unreadCount", 0);
            sessionUpdate.put("updateTime", session.getUpdateTime());
            
            String sessionUpdateJson = objectMapper.writeValueAsString(sessionUpdate);
            LOGGER.info("发送会话更新消息: {}", sessionUpdateJson);
            
            // 发送给用户
            ChatWebSocketServer.sendMessage(session.getUserId(), sessionUpdateJson);
            
            // 发送给服务人员（使用服务人员的用户ID）
            ChatWebSocketServer.sendMessage(staff.getUserId(), sessionUpdateJson);
            
            LOGGER.info("清空通知已发送给双方");
        } catch (Exception e) {
            LOGGER.error("发送清空通知失败", e);
        }
        
        LOGGER.info("清空会话聊天记录成功: sessionId={}", sessionId);
    }

    /**
     * 删除聊天会话
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteSession(Long sessionId) {
        ChatSession session = sessionMapper.selectById(sessionId);
        if (session == null) {
            throw new ServiceException("会话不存在");
        }
        
        // 先删除会话下的所有消息
        clearSessionMessages(sessionId);
        
        // 再删除会话
        sessionMapper.deleteById(sessionId);
        
        LOGGER.info("删除聊天会话成功: sessionId={}", sessionId);
    }

    /**
     * 获取用户未读消息总数
     */
    public int getUnreadMessageCount(Long userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }
        
        LambdaQueryWrapper<ChatSession> queryWrapper = new LambdaQueryWrapper<>();
        
        if ("STAFF".equals(user.getRoleCode())) {
            // 如果是服务人员，查找服务人员ID
            ServiceStaff staff = staffMapper.selectOne(
                new LambdaQueryWrapper<ServiceStaff>()
                    .eq(ServiceStaff::getUserId, userId)
            );
            
            if (staff != null) {
                queryWrapper.eq(ChatSession::getStaffId, staff.getId());
                // 只统计最后发送者不是自己的会话
                queryWrapper.ne(ChatSession::getLastSenderId, userId);
            } else {
                return 0;
            }
        } else {
            // 普通用户直接查询
            queryWrapper.eq(ChatSession::getUserId, userId);
            // 只统计最后发送者不是自己的会话
            queryWrapper.ne(ChatSession::getLastSenderId, userId);
        }
        
        // 统计未读消息总数
        return sessionMapper.selectList(queryWrapper)
            .stream()
            .mapToInt(ChatSession::getUnreadCount)
            .sum();
    }

    /**
     * 获取聊天记录(针对特定会话)
     */
    public Page<ChatMessage> getChatMessages(Long sessionId, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<ChatMessage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatMessage::getSessionId, sessionId)
                .orderByAsc(ChatMessage::getCreateTime);
        
        Page<ChatMessage> page = messageMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
        
        // 填充用户信息
        fillUserInfo(page.getRecords());
        
        return page;
    }

    /**
     * 获取所有聊天记录(管理后台使用)
     */
    public Page<ChatMessage> getAllChatMessages(Integer pageNum, Integer pageSize, String content) {
        LambdaQueryWrapper<ChatMessage> queryWrapper = new LambdaQueryWrapper<>();
        
        // 如果有搜索内容,添加内容搜索条件
        if (StringUtils.hasText(content)) {
            queryWrapper.like(ChatMessage::getContent, content);
        }
        
        queryWrapper.orderByDesc(ChatMessage::getCreateTime);
        Page<ChatMessage> page = messageMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
        
        // 填充用户信息
        fillUserInfo(page.getRecords());
        
        return page;
    }

    /**
     * 填充用户信息
     */
    public void fillUserInfo(List<ChatMessage> messages) {
        for (ChatMessage message : messages) {
            // 填充发送者信息
            User sender = userMapper.selectById(message.getSenderId());
            message.setSender(sender);
            
            // 填充接收者信息
            User receiver = userMapper.selectById(message.getReceiverId());
            message.setReceiver(receiver);
        }
    }
}